﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ProjectHopur23.Models;
using ProjectHopur23.Repositories;

namespace ProjectHopur23.Controllers
{
	public class AdminController : Controller
	{
		#region Variables
		private IRepository rep = null;
		#endregion

		#region Constructors
		public AdminController(IRepository r)
		{
			rep = r;
		}

		public AdminController()
		{
			rep = new Repository();
		}
		#endregion

		#region Functions
		[Authorize(Roles = "Administrators")]
		public ActionResult Home()
		{
			return View();
		}

		[Authorize(Roles = "Administrators")]
		public ActionResult Users()
		{
			IEnumerable<UserProfile> users = rep.GetAllUsers();

			return View(users);
		}

		[Authorize(Roles = "Administrators")]
		public ActionResult Games()
		{
			IEnumerable<Game> games = rep.GetAllGames();

			return View(games);
		}

		[HttpGet]
		[Authorize(Roles = "Administrators")]
		public ActionResult ChangeUser(int? id)
		{
			if(id == null)
			{
				return View("Error");
			}

			UserProfile u = (from up in rep.GetAllUsers()
					where up.UserId == id.Value
					select up).FirstOrDefault();

			if(u == null)
			{
				return View("Error");
			}

			return View(u);
		}

		/// <summary>
		/// This method takes the change user form, performs a lot of error checking on it and submits the changes to database if everything was successful.
		/// </summary>
		[HttpPost]
		[Authorize(Roles = "Administrators")]
		public ActionResult ChangeUser(UserProfile u)
		{
			bool valid = true;

			if(String.IsNullOrEmpty(u.UserName))
			{
				ModelState.AddModelError("UserName", "Það verður að skilgreina notendanafn");
				valid = false;
			}
			else
			{
				UserProfile duplicate = (from up in rep.GetAllUsers()
							where up.UserName == u.UserName && up.UserId != u.UserId
							select up).FirstOrDefault();

				if(duplicate != null)
				{
					ModelState.AddModelError("UserName", "Þetta notendanafn er nú þegar skráð");
					valid = false;
				}
			}

			if(String.IsNullOrEmpty(u.email))
			{
				ModelState.AddModelError("email", "Það verður að skilgreina netfang");
				valid = false;
			}
			else
			{
				UserProfile duplicate = (from up in rep.GetAllUsers()
							where up.email == u.email && up.UserId != u.UserId
							select up).FirstOrDefault();

				if(duplicate != null)
				{
					ModelState.AddModelError("email", "Þetta netfang er nú þegar skráð");
					valid = false;
				}
			}

			if(valid == false)
			{
				return View(u);
			}

			try
			{
				UserProfile theUser = rep.GetAllUsers().First(up => up.UserId == u.UserId);
				theUser.email = u.email;
				theUser.UserName = u.UserName;
				theUser.score = u.score;
				rep.Save();
			}
			catch(Exception e)
			{
				System.Diagnostics.Debug.WriteLine("Error in ChangeUser\n" + e.ToString());
				return RedirectToAction("Error");
			}

			return RedirectToAction("Home");
		}

		[HttpGet]
		[Authorize(Roles = "Administrators")]
		public ActionResult AddGame()
		{
			Game g = new Game();

			return View(g);
		}

		/// <summary>
		/// This method takes the add game form, performs a lot of error checking on it and submits the changes to database if everything was successful.
		/// </summary>
		[HttpPost]
		[Authorize(Roles = "Administrators")]
		public ActionResult AddGame(Game g)
		{
			if(IsValidGameForm(g, 0) == false)
			{
				return View(g);
			}

			Game newGame = new Game {
				name = g.name,
				engName = g.engName,
				description = g.description,
				imageURL = "~/Images/" + g.imageURL,
				minPlayers = g.minPlayers,
				maxPlayers = g.maxPlayers};

			rep.AddGame(newGame);
			rep.Save();

			return RedirectToAction("Home");
		}

		[HttpGet]
		[Authorize(Roles = "Administrators")]
		public ActionResult ChangeGame(int? id)
		{
			if(id == null)
			{
				return View("Error");
			}

			Game g = (from gm in rep.GetAllGames()
					where gm.ID == id.Value
					select gm).FirstOrDefault();

			if(g == null)
			{
				return View("Error");
			}

			g.imageURL = g.imageURL.Substring(9);
			return View(g);
		}

		/// <summary>
		/// This method takes the change game form, performs a lot of error checking on it and submits the changes to database if everything was successful.
		/// </summary>
		[HttpPost]
		[Authorize(Roles = "Administrators")]
		public ActionResult ChangeGame(Game g)
		{
			if(IsValidGameForm(g, 1) == false)
			{
				return View(g);
			}

			try
			{
				Game theGame = rep.GetAllGames().First(gm => gm.ID == g.ID);
				theGame.name = g.name;
				theGame.engName = g.engName;
				theGame.imageURL = "~/Images/" + g.imageURL;
				theGame.description = g.description;
				theGame.minPlayers = g.minPlayers;
				theGame.maxPlayers = g.maxPlayers;
				rep.Save();
			}
			catch(Exception e)
			{
				System.Diagnostics.Debug.WriteLine("Error in ChangeGame\n" + e.ToString());
				return RedirectToAction("Error");
			}

			return RedirectToAction("Home");
		}

		/// <summary>
		/// This function takes a game instance and mode number as arguments and determines if the data in the game instance is valid.
		/// Mode = 0 means add, mode 1 means change/edit
		/// </summary>
		bool IsValidGameForm(Game g, int mode)
		{
			bool valid = true;

			if(String.IsNullOrEmpty(g.name))
			{
				ModelState.AddModelError("name", "Þú verður að skilgreina nafn fyrir leikinn");
				valid = false;
			}
			else
			{
				// If name isn't null or empty we should see if another game already has it
				// In add mode (mode == 0) we just need to check for the name
				Game duplicateName;
				if(mode == 0)
				{
					duplicateName = (from gm in rep.GetAllGames()
								where gm.name == g.name
								select gm).FirstOrDefault();
				}
				// but we also need to rule out equal IDs if we are in change mode (mode == 1)
				else
				{
					duplicateName = (from gm in rep.GetAllGames()
								where gm.name == g.name && gm.ID != g.ID
								select gm).FirstOrDefault();
				}

				if(duplicateName != null)
				{
					ModelState.AddModelError("name", "Þetta nafn er nú þegar til");
					valid = false;
				}
			}

			if(String.IsNullOrEmpty(g.engName))
			{
				ModelState.AddModelError("engName", "Þú verður að skilgreina enskt nafn fyrir leikinn");
				valid = false;
			}
			else
			{
				// Same duplicate check logic as with the name property
				Game duplicateEngName;
				if(mode == 0)
				{
					duplicateEngName = (from gm in rep.GetAllGames()
								where gm.engName == g.engName
								select gm).FirstOrDefault();
				}
				else
				{
					duplicateEngName = (from gm in rep.GetAllGames()
								where gm.engName == g.engName && gm.ID != g.ID
								select gm).FirstOrDefault();
				}

				if(duplicateEngName != null)
				{
					ModelState.AddModelError("engName", "Þetta enska nafn er nú þegar til");
					valid = false;
				}
			}

			if(String.IsNullOrEmpty(g.imageURL))
			{
				ModelState.AddModelError("imageURL", "Þú verður að skilgreina skráarnafn fyrir myndina");
				valid = false;
			}
			else
			{
				// TODO: some regular expression stuff
			}

			if(String.IsNullOrEmpty(g.description))
			{
				ModelState.AddModelError("description", "Þú verður að lýsa leiknum");
				valid = false;
			}

			if(g.maxPlayers < 2)
			{
				ModelState.AddModelError("maxPlayers", "Hámarksfjöldi leikmanna má ekki vera undir 2");
				valid = false;
			}

			if(g.minPlayers < 2)
			{
				ModelState.AddModelError("minPlayers", "Lágmarksfjöldi leikmanna má ekki vera undir 2");
				valid = false;
			}

			if(g.maxPlayers <  g.minPlayers)
			{
				ModelState.AddModelError("maxPlayers", "Hámarksfjöldi leikmanna má ekki vera undir lágmarksfjölda");
				valid = false;
			}

			if(valid == false)
			{
				return false;
			}

			return true;
		}
		#endregion
	}
}
